package com.example.saiaadmin.config;

import com.example.saiaadmin.filter.JWTAuthenticationFilter;
import com.example.saiaadmin.hander.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * security配置类
 * https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/index.html#servlet-authentication-unpwd 官网
 * 登录请求后，可先看 UsernamePasswordAuthenticationFilter 源码逻辑
 */
@Configuration
@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true)//允许在方法上使用表达式定义安全规则
public class SecurityConfig  {

    //自定义的userDetailsServiceImpl
    @Autowired
    private UserDetailsService userDetailsServiceImpl;
    //JWT过滤器
    @Autowired
    private JWTAuthenticationFilter jwtAuthenticationFilter;

    //匿名未登录的时候访问
    @Autowired
    private AnonymousNotLoggedInAuthentication anonymousNotLoggedInAuthentication;

    //登陆失败
    @Autowired
    private LoginAuthenticationFailHandler loginAuthenticationFailHandler;

    //登录成功后，调用的方法
    @Autowired
    private LoginAuthenticationSuccessHandler loginAuthenticationSuccessHandler;

    //退出成功
    @Autowired
    private LogoutAuthenticationSuccessHandler logoutAuthenticationSuccessHandler;

    //没有权限,被拒绝访问时的调用类
    @Autowired
    private MissingRestAccessDeniedHandler missingRestAccessDeniedHandler;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable()) // 基于token，不需要csrf
                .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 基于token，不需要session，在/logout登出的时候会拿不到用户实体对象。
                .authorizeHttpRequests((authz) -> authz
                        .requestMatchers("/eb-system-user/register","/eb-system-user/login", "/eb-system-user/getCode","/eb-system-login-log/getLoginLogList").permitAll() // 放行api /error
                        .requestMatchers(HttpMethod.OPTIONS).permitAll()
                        .anyRequest().authenticated()

                )
                .cors(Customizer.withDefaults())//允许跨域
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        http.exceptionHandling(exception ->{
                    //访问没有权限处理类
                     exception.accessDeniedHandler(missingRestAccessDeniedHandler)
                      //匿名访问
                      .authenticationEntryPoint(anonymousNotLoggedInAuthentication);
                })
                .formLogin(from->{
                    from
                          //  .loginProcessingUrl("/login")
                            // 登陆成功后，也可以进行转发
                       // .successHandler(loginAuthenticationSuccessHandler)
                            // 登陆失败后 ，也可以进行转发
                       // .failureHandler(loginAuthenticationFailHandler)
                            // 前后端分离，禁用默认表单登录
                        .disable()
                    ;
                })
                // 退出操作，不建议在此处理，更建议使用自定义方法处理
                .logout(logout->{
                    logout
                         //   .logoutSuccessHandler(logoutAuthenticationSuccessHandler)
                          .disable();// 前后端分离，禁用登出页面
                });

        return http.build();
    }

    /**
     * 处理身份验证
     */
    @Bean
    public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsServiceImpl);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return new ProviderManager(authenticationProvider);
    }

    /**
     * 密码加密
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 静态资源放行
     */
    /*@Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers(
                "/doc.html",
                "/doc.html/**",
                "/v3/api-docs",
                "/v3/api-docs/**",
                "/webjars/**",
                "/authenticate",
                "/swagger-ui.html/**",
                "/swagger-resources",
                "/swagger-resources/**"
        );
    }*/
}